/*
 * Copyright (C) RT, 2017 by kiterunner_t
 * TO THE HAPPY FEW
 */

package com.guijq.codesegment.schedule.usage;


import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.guijq.codesegment.exception.BaseException;
import com.guijq.codesegment.exception.ErrorType;
import lombok.extern.slf4j.Slf4j;
import org.quartz.CronExpression;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.DateBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;


import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;


@Component
@Slf4j
public class JobSchedulingUtils {

    @Autowired
    private Scheduler scheduler;
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public JobSchedulingUtils() {

        try {
//            scheduler = schedulerFactory.getScheduler();
//
//            scheduler.start();
//            addtestJob(ReportTimingBufferJob.class, "reportid1", "qcPlanId", 1, null, 1);
//            addtestJob(ReportTimingBufferJob.class, "reportid2", "qcPlanId", 2, null, 2);
//            addtestJob(ReportTimingBufferJob.class, "reportid3", "qcPlanId", 3, null, 3);
//            addtestJob(ReportTimingBufferJob.class, "reportid4", "qcPlanId", 4, null, 4);
//            addtestJob(ReportTimingBufferJob.class, "reportid5", "qcPlanId", 5, null, 5);
//            addtestJob(ReportTimingBufferJob.class, "reportid6", "qcPlanId", 6, null, 6);
//            addtestJob(ReportTimingBufferJob.class, "reportid7", "qcPlanId", 7, null, 7);
//            addtestJob(ReportTimingBufferJob.class, "reportid8", "qcPlanId", 8, null, 8);
//            addtestJob(ReportTimingBufferJob.class, "reportid9", "qcPlanId", 9, null, 9);
//            addtestJob(ReportTimingBufferJob.class, "reportid10", "qcPlanId", 10, null, 10);
//            addtestJob(ReportTimingBufferJob.class, "reportid11", "qcPlanId", 11, null, 11);
//            addtestJob(ReportTimingBufferJob.class, "reportid12", "qcPlanId", 12, null, 12);
//            addtestJob(ReportTimingBufferJob.class, "reportid13", "qcPlanId", 13, null, 13);
//            addtestJob(ReportTimingBufferJob.class, "reportid14", "qcPlanId", 14, null, 14);
//            addtestJob(ReportTimingBufferJob.class, "reportid15", "qcPlanId", 15, null, 15);
        } catch (Exception ex) {
            throw new BaseException("调度器启动失败：" + ex.getMessage(), ErrorType.ERROR.getIndex());
        }

    }

    public void addJob(Class jobClass, String jobName, String groupName, Object param, String expression) {
        try {
            JobDetail jobDetail = newJob(jobClass)
                    .withIdentity(jobName, groupName)
                    .build();
            jobDetail.getJobDataMap().put("param", param);

            // Trigger the job to run now
            Trigger trigger = newTrigger()
                    .withIdentity(jobName, groupName)
                    .withSchedule(CronScheduleBuilder.cronSchedule(expression))
                    .build();

            // Tell quartz to schedule the job using our trigger
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (Exception ex) {
            throw new BaseException("调度器添加任务失败：" + ex.getMessage(), ErrorType.ERROR.getIndex());
        }
    }

    public void addJob(Class jobClass, String jobName, String groupName, Object param, int interval) {
        try {
            JobDetail jobDetail = newJob(jobClass)
                    .withIdentity(jobName, groupName)
                    .build();
            jobDetail.getJobDataMap().put("param", param);


            // Trigger the job to run now
            Trigger trigger = newTrigger()
                    .withIdentity(jobName, groupName)
                    .startAt(DateBuilder.futureDate(interval, DateBuilder.IntervalUnit.MINUTE))
                    .build();

            // Tell quartz to schedule the job using our trigger
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (Exception ex) {
            throw new BaseException("调度器添加任务失败：" + ex.getMessage(), ErrorType.ERROR.getIndex());
        }
    }

    public boolean isExistTrigger(TriggerKey triggerKey) {
        try {
            return scheduler.checkExists(triggerKey);
        } catch (SchedulerException e) {
            throw new BaseException("调度器查询触发器是否存在失败：" + e.getMessage());
        }
    }

    public boolean isExistTrigger(String name, String group) {
        TriggerKey triggerKey = new TriggerKey(name, group);
        return isExistTrigger(triggerKey);
    }

    public void ddd(String group) {
        try {
            scheduler.getTriggerKeys(GroupMatcher.groupEquals(group));
        } catch (SchedulerException e) {
            throw new BaseException("调度器查询触发器失败：" + e.getMessage());
        }
    }

    public boolean isExistJob(JobKey jobKey) {
        try {
            return scheduler.checkExists(jobKey);
        } catch (SchedulerException e) {
            throw new BaseException("调度器查询触发器是否存在失败：" + e.getMessage());
        }
    }

    public void modifyTrigger(String name, String group, String cronExpression) {
        TriggerKey triggerKey = new TriggerKey(name, group);
        try {
            if (StringUtils.isEmpty(cronExpression)) {
                throw new BaseException("调度器时间表达式不正确");
            }
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if (null != trigger.getCronExpression() && !trigger.getCronExpression().equals(cronExpression)) {
                trigger.getTriggerBuilder().withSchedule(CronScheduleBuilder.cronSchedule(cronExpression));
                scheduler.rescheduleJob(triggerKey, trigger);
            }
        } catch (SchedulerException e) {
            throw new BaseException("更新触发器失败：" + e.getMessage());
        }
    }

    /**
     */
    public void skipNextSchedule(String name, String group) {
        try {
            TriggerKey triggerKey = new TriggerKey(name, group);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            Date nexFireTime = trigger.getNextFireTime();
            Timestamp start = new Timestamp(nexFireTime.getTime() + 1000);
            trigger.getTriggerBuilder().startAt(start);
            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void addScheduleJob(Class jobClass, String jobName, String groupName, Timestamp startTime, Timestamp endTime, Object param, String cronExpressionStr) {
        try {
            JobDetail jobDetail = newJob(jobClass)
                    .withIdentity(jobName, groupName)
                    .build();
            jobDetail.getJobDataMap().put("param", param);


            // Trigger the job to run now
            Trigger trigger = newTrigger()
                    .withIdentity(jobName, groupName)
                    .startAt(startTime)
                    .endAt(endTime)
                    .withSchedule(CronScheduleBuilder.cronSchedule(new CronExpression(cronExpressionStr)))
                    .build();

            // Tell quartz to schedule the job using our trigger
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (Exception ex) {
            throw new BaseException("调度器添加任务失败：" + ex.getMessage(), ErrorType.ERROR.getIndex());
        }
    }

    public void addScheduleJob(Class jobClass, String jobName, String groupName, int interval, Object param) {
        try {
            JobDetail jobDetail = newJob(jobClass)
                    .withIdentity(jobName, groupName)
                    .build();
            jobDetail.getJobDataMap().put("param", param);
            // Trigger the job to run now
            Trigger trigger = newTrigger()
                    .withIdentity(jobName, groupName)
                    .startAt(DateBuilder.futureDate(interval, DateBuilder.IntervalUnit.MINUTE))
                    .withSchedule(simpleSchedule()
                            .withIntervalInMinutes(interval)
                            .repeatForever())
                    .build();

            // Tell quartz to schedule the job using our trigger
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (Exception ex) {
            throw new BaseException("调度器添加任务失败：" + ex.getMessage(), ErrorType.ERROR.getIndex());
        }
    }


    /**
     * 移除触发器
     * @param triggerKey
     */
    public void removeTrigger(TriggerKey triggerKey) {
        try {
            scheduler.unscheduleJob(triggerKey);
        } catch (SchedulerException ex) {
            throw new BaseException("调度器移除触发器失败：" + ex.getMessage(), ErrorType.ERROR.getIndex());
        }
    }

    public void removeJob(String jobName, String jobGroup) {
        JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
        removeJob(jobKey);
    }

    public void removeJob(JobKey jobKey) {
        try {
            scheduler.deleteJob(jobKey);
        } catch (SchedulerException ex) {
            throw new BaseException("调度器移除任务失败：" + ex.getMessage(), ErrorType.ERROR.getIndex());
        }
    }

    public void stop() {
        try {
            scheduler.shutdown();
        } catch (SchedulerException ex) {
            throw new BaseException("调度器停止失败：" + ex.getMessage(), ErrorType.ERROR.getIndex());
        }
    }

    /**
     * 暂停job
     *
     * @param jobKey
     */
    public void pauseJob(JobKey jobKey) {
        try {
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException ex) {
            throw new BaseException("调度器暂停任务失败：" + ex.getMessage(), ErrorType.ERROR.getIndex());
        }

    }

    /**
     * 暂停触发器
     * @param triggerKey
     */
    public void pauseTrigger(TriggerKey triggerKey) {
        try {
            scheduler.pauseTrigger(triggerKey);
        } catch (SchedulerException ex) {
            throw new BaseException("调度器暂停触发器失败：" + ex.getMessage(), ErrorType.ERROR.getIndex());
        }
    }

    /**
     * 恢复job
     *
     * @param jobKey
     */
    public void resumeJob(JobKey jobKey) {
        try {
            scheduler.resumeJob(jobKey);
        } catch (SchedulerException ex) {
            throw new BaseException("调度器恢复任务失败：" + ex.getMessage(), ErrorType.ERROR.getIndex());
        }

    }

    /**
     * 恢复
     * @param triggerKey
     */
    public void resumeTrigger(TriggerKey triggerKey) {
        try {
            scheduler.resumeTrigger(triggerKey);
        } catch (SchedulerException ex) {
            throw new BaseException("调度器恢复触发器失败：" + ex.getMessage(), ErrorType.ERROR.getIndex());
        }
    }


}

